#### The complete picture: all Bible books
The table below summarises every Bible book that appears in the data — Folger marks,
Shaheen references, Stritmatter additions and matches — sortable by any column.
Books are in canonical Bible order by default. Sort by **Shaheen refs** to see immediately
where Shakespeare's attention fell; sort by **Folger marks** to see where the annotator's
did. The two lists do not coincide.
```{r}
#| echo: false
#| message: false
#| warning: false
library(DT)
library(dplyr)
library(stringr)
library(ggplot2)
library(tidyr)
library(purrr)
cb <- readr::read_csv("cb16.csv", show_col_types = FALSE)
```
# ---------------------------------------------------------------
# CHART 2: scatter — marks vs shaheen refs, labelled
# ---------------------------------------------------------------
scatter_data <- book_summary %>%
filter(marks > 0 | shaheen > 10) %>%
mutate(label = ifelse(marks > 5 | shaheen > 50, booklink_clean, ""))
ggplot(scatter_data, aes(x=shaheen, y=marks, label=label)) +
geom_point(aes(colour=testament), size=2.5, alpha=0.8) +
geom_text(nudge_y=1.5, size=2.8, colour="#444", family="sans") +
scale_colour_manual(values=c("OT"="#6b3a2a","NT"="#4a6741","Ap"="#888888"),
labels=c("Old Testament","New Testament","Apocrypha"),
na.value="#aaaaaa") +
labs(x="Shaheen references", y="Folger marks",
colour=NULL,
title="Marks vs references: the scatter tells the story",
subtitle="Books in the top-right would support the Oxfordian claim. None are there.") +
theme_minimal(base_family="sans") +
theme(
plot.title = element_text(size=11, face="bold", colour="#3d0e0e"),
plot.subtitle = element_text(size=8, colour="#666"),
legend.position = "top"
)
# ---------------------------------------------------------------
# BUILD BOOK-LEVEL SUMMARY
# Marks keyed on 'book', references on 'booklink'
# ---------------------------------------------------------------
cb_summary <- cb %>%
mutate(
booklink_clean = str_replace_all(trimws(booklink), "\\+", " "),
book_clean = trimws(book)
)
mark_counts <- cb_summary %>%
filter(!sourcetype %in% c("ShakRef","StritAdd","StritDirect","StritIndirect",""),
!is.na(sourcetype)) %>%
group_by(book_clean) %>%
summarise(marks = n(), .groups="drop") %>%
rename(booklink_clean = book_clean)
ref_counts <- cb_summary %>%
filter(!is.na(booklink_clean), booklink_clean != "") %>%
group_by(booklink_clean) %>%
summarise(
shaheen = sum(sourcetype == "ShakRef", na.rm=TRUE),
s_add = sum(sourcetype == "StritAdd", na.rm=TRUE),
s_dir = sum(sourcetype == "StritDirect",na.rm=TRUE),
s_ind = sum(sourcetype == "StritIndirect",na.rm=TRUE),
matches = sum(diagnosticmatch == "FBM", na.rm=TRUE),
testament = first(na.omit(testament)),
book_order= min(book.order.key, na.rm=TRUE),
.groups="drop"
)
book_summary <- ref_counts %>%
left_join(mark_counts, by="booklink_clean") %>%
mutate(marks = coalesce(marks, 0L)) %>%
filter(shaheen > 0 | s_add > 0 | s_dir > 0 | s_ind > 0) %>%
arrange(book_order) %>%
mutate(
total_refs = shaheen + s_add + s_dir + s_ind,
odds_n = ifelse(marks > 0, round(shaheen / marks), NA_integer_),
odds_sort = ifelse(is.na(odds_n), 99999L, odds_n),
odds_display = case_when(
marks == 0 ~ "—",
odds_n == 0 ~ "1:0",
TRUE ~ paste0("1:", odds_n)
),
testament = case_when(
testament == "Old" ~ "OT",
testament == "New" ~ "NT",
TRUE ~ testament
)
)
# ---------------------------------------------------------------
# TABLE
# ---------------------------------------------------------------
datatable(
book_summary %>%
select(booklink_clean, testament, marks, shaheen,
s_add, s_dir, s_ind, matches, odds_display, odds_sort),
colnames = c("Book", "T", "Folger marks", "Shaheen refs",
"Strit. add.", "Strit. direct", "Strit. indirect",
"Matches", "Odds", "odds_sort"),
rownames = FALSE,
escape = FALSE,
filter = 'top',
options = list(
paging = TRUE,
pageLength = 25,
lengthMenu = list(c(25, 50, -1), c("25","50","All")),
scrollX = TRUE,
autoWidth = FALSE,
dom = 'lfrtip',
order = list(list(2, 'desc')), # default: sort by Shaheen refs desc
columnDefs = list(
list(width='160px', targets=0),
list(width='35px', targets=1, className='dt-center'),
list(width='90px', targets=2, className='dt-center'),
list(width='90px', targets=3, className='dt-center'),
list(width='80px', targets=4, className='dt-center'),
list(width='80px', targets=5, className='dt-center'),
list(width='80px', targets=6, className='dt-center'),
list(width='70px', targets=7, className='dt-center'),
list(width='70px', targets=8, className='dt-center'),
list(visible=FALSE, targets=9) # hide numeric odds sort column
),
initComplete = JS(
"function(settings, json) {",
" $(this.api().table().container()).css({",
" 'font-family': 'Fira Sans Condensed, sans-serif',",
" 'font-size': '0.82rem'",
" });",
"}"
)
)
) %>%
formatStyle('booklink_clean',
fontWeight = 'bold', color = '#3d0e0e') %>%
formatStyle('marks',
background = styleColorBar(range(book_summary$marks), '#c8b09080'),
backgroundSize = '98% 60%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle('shaheen',
background = styleColorBar(range(book_summary$shaheen), '#4a674180'),
backgroundSize = '98% 60%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle('odds_display',
fontWeight = 'bold', color = '#800000', textAlign = 'center')
#| echo: false
#| message: false
#| fig-width: 9
#| fig-height: 6
#| fig-cap: "Folger marks vs Shaheen references by Bible book (top 25 by total references). The mismatch between where Shakespeare looked and where the annotator marked is the core of the argument."
# ---------------------------------------------------------------
# CHART: marks vs refs, top 25 books by shaheen refs
# ---------------------------------------------------------------
# rebuild book_summary in case it didn't persist from chunk 1
book_summary <- ref_counts %>%
left_join(mark_counts, by="booklink_clean") %>%
mutate(marks = coalesce(marks, 0L)) %>%
filter(shaheen > 0 | s_add > 0 | s_dir > 0 | s_ind > 0) %>%
arrange(book_order) %>%
mutate(
total_refs = shaheen + s_add + s_dir + s_ind,
odds_n = ifelse(marks > 0, round(shaheen / marks), NA_integer_),
odds_sort = ifelse(is.na(odds_n), 99999L, odds_n),
odds_display = case_when(
marks == 0 ~ "—",
odds_n == 0 ~ "1:0",
TRUE ~ paste0("1:", odds_n)
),
testament = case_when(
testament == "Old" ~ "OT",
testament == "New" ~ "NT",
TRUE ~ testament
)
)
top25 <- book_summary %>%
arrange(desc(shaheen)) %>%
slice_head(n=25) %>%
mutate(book = factor(booklink_clean,
levels=rev(booklink_clean)))
# Reshape for grouped bars
plot_data <- bind_rows(
top25 %>% transmute(book, value=marks, type="Folger marks"),
top25 %>% transmute(book, value=shaheen, type="Shaheen refs")
)
ggplot(plot_data, aes(x=book, y=value, fill=type)) +
geom_col(position=position_dodge(width=0.7), width=0.6) +
scale_fill_manual(values=c("Folger marks"="#6b3a2a",
"Shaheen refs"="#4a6741")) +
coord_flip() +
labs(x=NULL, y="Count", fill=NULL,
title="Where Shakespeare looked vs where the annotator marked",
subtitle="Top 25 Bible books by Shaheen reference count") +
theme_minimal(base_family="sans") +
theme(
plot.title = element_text(size=11, face="bold", colour="#3d0e0e"),
plot.subtitle = element_text(size=8, colour="#666"),
legend.position = "top",
legend.text = element_text(size=9),
axis.text.y = element_text(size=8),
panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank()
)
#| echo: false
#| message: false
#| fig-width: 7
#| fig-height: 5
#| fig-cap: "Books with Folger marks but few or no Shakespeare references — the annotator marked these; Shakespeare largely ignored them."
# ---------------------------------------------------------------
# CHART 2: scatter — marks vs shaheen refs, interactive
# ---------------------------------------------------------------
library(plotly)
scatter_data <- book_summary %>%
filter(marks > 0 | shaheen > 10) %>%
mutate(
testament_label = case_when(
testament == "OT" ~ "Old Testament",
testament == "NT" ~ "New Testament",
testament == "Ap" ~ "Apocrypha",
TRUE ~ "Unknown"
),
hover_text = paste0(
"", booklink_clean, "
",
"Shaheen refs: ", shaheen, "
",
"Folger marks: ", marks, "
",
"Strit. additions: ", s_add, "
",
"Matches: ", matches, "
",
testament_label
)
)
p <- ggplot(scatter_data,
aes(x=shaheen, y=marks,
colour=testament,
text=hover_text)) +
geom_point(size=2.5, alpha=0.85) +
scale_colour_manual(
values = c("OT"="#6b3a2a","NT"="#4a6741","Ap"="#888888"),
labels = c("Old Testament","New Testament","Apocrypha"),
na.value = "#aaaaaa"
) +
labs(
x = "Shaheen references",
y = "Folger marks",
colour = NULL,
title = "Marks vs references: the scatter tells the story",
subtitle = "Books in the top-right would support the Oxfordian claim. None are there."
) +
theme_minimal(base_family="sans") +
theme(
plot.title = element_text(size=11, face="bold", colour="#3d0e0e"),
plot.subtitle = element_text(size=8, colour="#666"),
legend.position = "top"
)
ggplotly(p, tooltip="text") %>%
layout(
hoverlabel = list(
bgcolor = "#1a1a1a",
font = list(family="Fira Sans Condensed", size=12, color="#f5f1e8"),
bordercolor = "#3d0e0e"
)
)
```